package org.myOrg.spetrum.combination;

import java.util.ArrayList;
import java.util.List;

import org.myOrg.spetrum.testObject.TestCase;

public class TupleCaseImplement implements TupleCase {

	public TupleCaseImplement() {
	}

	@Override
	public List<Tuple> getTuplesFromCase(TestCase testCase, int degree) {
		int caseLength = testCase.getLength(); //the num of case		
		 List<Tuple> tuples = new ArrayList<Tuple>();
		
        int currentPoint = 0;
        CombineStack stack = new CombineStack(degree);
        while(true){
            if(stack.isFull()){
                tuples.add(stack.generateTuple());
            	stack.pop();
            }
            else if(currentPoint == caseLength){
            	if(stack.isEmpty())
            		break;
            	stack.pop();
            	currentPoint = stack.getParamIndex(stack.currentIndex)+1;
            }
            else{
            	stack.push(currentPoint, testCase.getAt(currentPoint));
            	currentPoint++;
            }
        }
		return tuples ;
	}

	class CombineStack {
		int currentIndex;
		int allSize;
		Tuple tupleTemplate;
		public CombineStack(int degree){
			this.currentIndex = 0;
			this.allSize = degree;
			this.tupleTemplate =new TupleImplement(degree);
		}
		public boolean isFull(){
			return (currentIndex == allSize);
		}
		public boolean isEmpty(){
			return (currentIndex == 0);
		}
		public void push(int param ,int value){
			if(!isFull()){
			  tupleTemplate.set(currentIndex, param, value);
			  currentIndex++;
			}
		}
		public void pop(){
			if(!isEmpty())
			  currentIndex--;
		}
		public Tuple generateTuple(){
			return this.tupleTemplate.copy();
		}
		public int getParamIndex(int index){
		  return	this.tupleTemplate.getParamIndex()[index];
		}
	}

	@Override
	public TestCase getCaseFromTuple(Tuple tuple, TestCase caseExample) {
		// TODO Auto-generated method stub
		TestCase result = caseExample.copy();
		for(int i = 0 ; i < tuple.getDegree() ; i++){
			result.set(tuple.getParamIndex()[i], tuple.getParamValue()[i]);
		}
		return result;
	}

}
